
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h> /*misc 驱动框架头文件*/


/* 实现系统调用接口：open() */
static int aml_misc_open(struct inode *inode, struct file *file)
{
	pr_info("aml_misc_open() is called.\n");
	return 0;
}


/* 实现系统调用接口：close() */
static int aml_misc_close(struct inode *inode, struct file *file)
{
	pr_info("aml_misc_close() is called.\n");
	return 0;
}


/* 实现系统调用接口：ioctl() */
static long aml_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	pr_info("aml_misc_ioctl() is called. cmd = %d, arg = %ld\n", cmd, arg);
	return 0;
}

static const struct file_operations aml_misc_fops = {
	.owner = THIS_MODULE,  /* 固定搭配 */
	.open = aml_misc_open, /* 提供open()， fopen()系统调用 */
	.release = aml_misc_close, /* 提供close()， fclose()系统调用 */
	.unlocked_ioctl = aml_misc_ioctl, /* 提供ioctl()系统调用 */
};

/* 声明 struct miscdevice 结构体变量，并赋值*/
static struct miscdevice aml_misc_device = {
		.minor = MISC_DYNAMIC_MINOR,  /* 优点：misc设备已由misc框架提供了主设备号，其余设备通过此设定，自动分配一个次设备号*/
		.name = "aml_misc_dev",  /* 将创建/dev/aml_misc_dev    以及 /sys/class/misc/aml_misc_dev */
		.fops = &aml_misc_fops, 
};


/*
* 模块初始化接口
* 对比之前两篇文章的例子，可见此版本，有如下几个优点
* (1)不需去申请设备号
* (2)不需去创建和注册 struct class
* (3)不需去创建和注册 struct device
* (4)省去了一大堆，申请、注册的异常判断语句
*/
static int __init aml_misc_init(void)
{
	int ret;
	pr_info("aml_misc_init\n");

	/* 将miscdevice对象注册进内核 */
	ret = misc_register(&aml_misc_device);

	if (ret != 0) {
		pr_err("Failded: misc_register aml_misc_dev\n");
		return ret;
	}

	pr_info("init alloc aml_misc_dev's minor[%i]\n",aml_misc_device.minor);
	return 0;
}

/*同初始化函数，退出时候，也不需执行Major/Minor的反注册 */
static void __exit aml_misc_exit(void)
{
	pr_info("aml_misc_exit\n");

	/* 注销miscdevice对象 */
	misc_deregister(&aml_misc_device);

}

module_init(aml_misc_init);
module_exit(aml_misc_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("szhou <66176468@qq.com>");
MODULE_DESCRIPTION("simple say[3]: misc device driver");



